/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package edu.uoc.tfc.exuoc.controladors;

import edu.uoc.tfc.exuoc.model.InterfaceItem;
import edu.uoc.tfc.exuoc.model.Item;
import edu.uoc.tfc.exuoc.model.Contenidor;
import edu.uoc.tfc.exuoc.model.MetaDC;

import edu.uoc.tfc.exuoc.model.Arxiu;
import edu.uoc.tfc.exuoc.utils.seguretat.InjeccioCodi;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.Date;
import java.text.SimpleDateFormat;
import java.text.ParseException;
import org.hibernate.HibernateException;
import edu.uoc.tfc.exuoc.errors.NoExisteixException;
import edu.uoc.tfc.exuoc.errors.AfegirDAOException;
import edu.uoc.tfc.exuoc.errors.ModDAOException;
import edu.uoc.tfc.exuoc.errors.EliDAOException;
import edu.uoc.tfc.exuoc.errors.BuitException;
import edu.uoc.tfc.exuoc.errors.LlegirDAOException;
import edu.uoc.tfc.exuoc.errors.LlistatDAOException;
import edu.uoc.tfc.exuoc.errors.LogicException;
import java.io.UnsupportedEncodingException;
import edu.uoc.tfc.exuoc.config.Config;

import edu.uoc.tfc.exuoc.utils.Eines;


/**
 * classe que contindrà totes les funcionalitats dels objectes Item,
 * estableix la connexió amb l'objecte DAO per obtenir/enviar els objectes
 * de tipus Ítem
 * @author emoreno
 */
public class GestorItems implements InterfaceGestor{

    private static Integer numItems=Config.valorNullInt;
    private ItemsDAO dao;
    private GestorLogs  log;

    private static GestorItems INSTANCE = null;
    private GestorItems(){
        dao= new ItemsDAO();
        log=GestorLogs .getLogger(this.getClass().getName());

    };

    // creador sincronizado para protegerse de posibles problemas  multi-hilo
    // otra prueba para evitar instantiación múltiple
    private synchronized static void createInstance() {
        if (INSTANCE == null) {
            INSTANCE = new GestorItems();
        }

    }
    public static GestorItems getInstance() {
        if (INSTANCE == null) createInstance();
            return INSTANCE;
    }


   //Obre una connexió amb el gestor genèric de la persistència DAO
    @Override
    public void openGestor() throws HibernateException{
        if (this.dao==null) this.dao= new ItemsDAO();
    }
    // Mètode que tancarà la sessió oberta un cop ja no calgui
    @Override
    public void  tancar() throws HibernateException{
        try{
            if (dao!=null){
                dao.tancarConnexio();
                dao=null;
            }
        }catch(HibernateException e){
            this.getLog().error("GI:tancar:Hi ha hagut un error realitzant el "
               +"tancament amb la base de dades.{} ", e.getLocalizedMessage());
        }catch (NullPointerException e){
            this.log.info("GI:tancar:Gestor d'ítems ja tancat");
        }

    }

    @Override
    public GestorLogs  getLog() {
        return log;
    }

    @Override
    public void setLog(GestorLogs  log) {
        this.log = log;
    }



     public boolean existeix(InterfaceItem itm){
        boolean existeix=false;
        InterfaceItem it1=new Item();
        openGestor();
        try {

            Long id=itm.getId();
            if (id!=Config.valorNull){
                it1.setId(id);
                it1=dao.consultaItem(itm.getId());
                if (it1!=null ){
                    this.getLog().info("GI:existeix: Item trobat. id:"
                            +it1.getId()+" login:"+it1.getNom());
                    existeix=true;
                }
            }

        }catch (HibernateException e){
            log.error("GI:Existeix:Nou item login:"+itm.getNom()
                    +e.getLocalizedMessage());

        }catch (BuitException e){
            log.error("GI:Existeix:Valor buit. No s'ha trobat l`ítem. "
                    +e.getLocalizedMessage());

        }/*catch (UnsupportedEncodingException e){
            log.error("GI:Existeix:Error en la cadena de cerca where.item:"
                    +itm.getNom()+". "+e.getLocalizedMessage());

        }*/catch (NullPointerException e){
            log.error("GI:Existeix:possiblement l'ítem o el seu l'id sigui null."
                    +e.getLocalizedMessage());
        }

        it1=null;
        return existeix;
    }


    /**
     * S'afegeix un ítem nou.Cal que ja tingui assignat el contenidor a on anirà
     * l'arxiu i les metadades
     * @param nou
     * @return
     * @throws AfegirDAOException
     */
    public Long afegir(InterfaceItem nou)  throws AfegirDAOException{
        Long falla=-1L;

        //Es comprova que l'ítem no existeix
        if ( ! this.existeix(nou)){
        try {
            openGestor();
            //S'afegeix a la llista de contenidors;
            nou.getContenidor().addItem(nou);

            //es lliga a cada una de les metadades assignades. relació
            //bidireccional feta amb hibernate
/*          GestorMetadades gmd = GestorMetadades.getInstance();
            Iterator<MetaDC>  iter= nou.getMetesDC().iterator();
                while (iter.hasNext() ){
                    Long index=iter.next().getId();
                    MetaDC metadc=gmd.llegir(index);
                    metadc.addItem((Item)nou);
                }
*/          //Afegim l'ítem a cada metadada entrada.
/* 16-01-2012:Emili:1-N            int i=0;
            int mida=nou.getMetesDC().size();
            while (i < mida){
                nou.getMetesDC().get(i).addItem((Item)nou);
                i++;
            }
 *
 */
            
            falla=dao.afegirItem(nou);
            if (falla < 0 )throw new AfegirDAOException("GI:afegir: Item "
                    +" no afegit , id:"+nou.getId());
            //Actualitzacio Items
            this.numItems();
            
            //S'afegeix a la llista de contenidors;
            /*Emili:05-01-2012:
             nou.getContenidor().addItem(nou);
            GestorContenidors gc = GestorContenidors.getInstance();
            gc.modificar(nou.getContenidor());
            gc.tancar();
             * 
             */
        }catch (HibernateException ex){
            this.getLog().error("GI:Afegir:No s'ha pogut afegir l'ítem id:"
                    +nou.toString()+"."+ex.getLocalizedMessage());
            throw new AfegirDAOException("No s'ha pogut afegir l'ítem id:"
                    +nou.getId()) ;
            
        }catch (BuitException ex){
            this.getLog().error("No s'ha pogut afegir l'ítem id:"+nou.toString()
                    +"."+ex.getLocalizedMessage());
            throw new AfegirDAOException("GI:Afegir:No s'ha pogut afegir l'ítem "
                    +"id:"+nou.getId()) ;
        }catch (AfegirDAOException ex){
            this.getLog().error("GI:Afegir:No s'ha pogut afegir l'ítem id:"+
                    nou.toString()+"."+ex.getLocalizedMessage()
                    +" Algun valor null.");
            throw new AfegirDAOException("No s'ha pogut afegir l'ítem id:"+
                    nou.getId()) ;
        }/*catch (NoExisteixException ex){
            this.getLog().error("GI:Afegir:Error possiblement relacionant "
                    +"l'ítem amb una metadada"+nou.getContenidor().getId()
                    +" amb l'ítem id: "+nou.getId()
                    +". Algun valor null."+ex.getLocalizedMessage());
            throw new AfegirDAOException("GI:Afegir:No s'ha pogut actualitzar "
                    +"el conteidor amb l'íd:"+nou.getId()) ;
        }*/catch (NullPointerException ex){
            this.getLog().error("GI:afegir:No s'ha pogut afegir l'ítem id:"
                    +" S'ha intentat accedir a un valor null."
                    +ex.getLocalizedMessage());
            throw new AfegirDAOException("GI:Afegir:No s'ha pogut afegir l'ítem"+
                    " id:"+nou.getId()) ;
        }
        }else{
            log.error("GI:Afegir: l`ítem amb nom:"
                    +nou.getNom()+" ja existeix");
        }
        return falla;
    }


    private Long eliminar(Item item) throws EliDAOException {
        Long id=Config.valorNull;

        GestorContenidors gc= GestorContenidors.getInstance();
        Contenidor contenidor=null;
        try {
            openGestor();
            contenidor=item.getContenidor();
            id=item.getId();
            if (contenidor.getItems().remove(item)) id=-1L;
            if (gc.modificar(contenidor)==null) id=-11L;

            dao.eliminarItem(item);

            //Actualització NumItems
            this.numItems();
            //Emili:07-01-2012:this.numItems(-1);

        }catch (HibernateException e){
            this.getLog().error("GI:eliminar:No s'ha pogut eliminar l'ítem id:"
                    + Long.toString(item.getId()));
            throw new EliDAOException("GI:eliminar:Error de la bdd modificant "
                    +"l`ítem id:"+item.getId());
        }catch (BuitException e){
            this.getLog().error("GI:eliminar;No s'ha pogut eliminar l'ítem id:"+
                    Long.toString(item.getId()));
        }catch (NullPointerException e){
            this.getLog().error("GI:elminiar:Valors nulls a l'ítem id:"
                    +Long.toString(item.getId())+"."+ e.getMessage());
        }catch (ModDAOException e){
            this.getLog().error("GI:eliminar:no es pot modificar el contenidor "
                    +": "+contenidor.getNom()+"."+e.getMessage());
        }
        return id;
    }

    /**Crida des del ActionSupport per eliminar
     *
     * @param idItem
     * @param idContenidor
     * @return
     * @throws EliDAOException
     */
    public Long eliminar(Long idItem, Long idContenidor) throws EliDAOException {
        Long id=Config.valorNull;
        GestorContenidors gc = GestorContenidors.getInstance();
        try {
            openGestor();
            //El gestor de contenidors és el que gestiona les baixes.
           /* this.getLog().info("Contenidor: "+contenidor);
            this.getLog().info("Item: "+item);
            this.getLog().info("idContenidor: "+contenidor.getId());
            this.getLog().info("idItem: "+item.getId());*/


            //Es treu l'ítem de la llista d'ítems del contenidor
            gc.treureItem(idItem,idContenidor);
           // gc.tancar();
           // gc=null;

            
            //S'elimina l'ítem
            dao.eliminarItem(idItem);

            //Actualització NumItems
      // 16:45 20-12-11            this.numItems(-1);
      // 16:45 20-12-11           id=item.getId();

        }catch (HibernateException e){
            this.getLog().error("GI:Eliminar:No s'ha pogut eliminar l'ítem id:"
                    +idItem+". "+e.getLocalizedMessage());
            throw new EliDAOException("GI:Eliminar:Error de la bdd modificant o"
                    +"eliminant l`ítem id:"+idItem);
        }catch (BuitException e){
            this.getLog().error("GI:Eliminar:No s'ha pogut eliminar l'ítem id:"
                    +idItem+". "+e.getLocalizedMessage());
            throw new EliDAOException("GI:Elimnar:No s'ha pogut eliminar l'ítem "
                    +"id:"+idItem);
        }catch (NullPointerException e){
            this.getLog().error("GI:Eliminar:Valors nulls a l'ítem id:"+idItem
                    +". "+e.getLocalizedMessage());
            throw new EliDAOException("GI:Eliminar:Valors nulls a l'ítem ,id :"
                    + idItem);
        }finally{
            if (gc!=null){
                gc.tancar();
            }
        }

        return id;
    }

    public Long modificar(InterfaceItem actual) throws ModDAOException {
        Long falla=-1L;
        try {
            openGestor();
            dao.modificarItem(actual);
        }catch (HibernateException e){
            falla=-3L;
            this.getLog().error("GI:Modificar:No s'ha pogut modificar l'ítem "
            +actual.getNom()+". /n Amb id:"+actual.getId()+"."
                    +e.getLocalizedMessage());
            throw new ModDAOException("GI:Modificar:No s'ha pogut modificar "
                    +"l'ítem id:"+actual.getId() );
        }catch (BuitException e){
            falla=-31L;
            this.getLog().error("GI:Modificar:No s'ha pogut modificar l'ítem "
            +actual.getNom()+" amb id:"+actual.getId());
            throw new ModDAOException("GI:Modificar:No s'ha pogut modificar "+
                    "l'ítem, id:"+actual.getId());
        }
        return falla;
    }

    public boolean existeix(Item itm){
        boolean existeix=false;
        Item itm1=new Item();
        openGestor();
        try {

            Long id=itm.getId();
            if (id!=Config.valorNull){
                itm1.setId(id);
                itm1=dao.consulta("nom", itm.getNom());
                if (itm1!=null ){
                    Eines.escriu("Item trobat. id:"+itm1.getId()+" nom:"
                            +itm1.getNom());
                    existeix=true;
                }
            }

        }catch (HibernateException e){
            log.error("GI:Existeix:Nou item login:"+itm.getNom()
                    +".Possiblement nom repetit."+e.getLocalizedMessage());

        }catch (BuitException e){
            log.error("GI:Existeix:Valor buit. No s'ha trobat l`ítem. "
                    +e.getLocalizedMessage());

        }catch (UnsupportedEncodingException e){
            log.error("GU:Existeix:Error en la cadena de cerca where.Item:"
                    +itm.getNom()+". "+e.getLocalizedMessage());

        }catch (NullPointerException e){
            log.error("GI:Existeix:possiblement l'ítem o el seu l'id sigui null."
                    +e.getLocalizedMessage());
        }

        itm1=null;
        return existeix;
    }

    public InterfaceItem llegir(Long id) throws LlegirDAOException{
        InterfaceItem it=null;
        this.llegirItem(id);
        return it;
    }
    private InterfaceItem llegirItem(Long id) throws LlegirDAOException{
        InterfaceItem it=null;

        if (id==null ) return new Item();

        it=this.llegirItem(Item.class, id);
        return it;
    }
    private InterfaceItem llegirItem(Class classe,Long id)
            throws LlegirDAOException{
        InterfaceItem it=new Item();
        InterfaceItem item=null;

        it.setNom(Config.valorNullStr);
        it.setId(Config.valorNull);
        try{
            openGestor();
            //Tenim una visita més, que es veurà reflexada a la consulta següent
            //a aquesta.
            //dao.mesVisita(id);

            item=dao.consultaItem(classe, id);
            if (item!=null)
                it=item;
            else
                throw new LlegirDAOException("GI:Llegir:No s'ha trobat l'Ítem "
                        +"buscat amb id: "+id.toString()+","+this.getClass());
        }catch (HibernateException e){
            log.error("GI:Llegir:Hi ha hagut un error realitzant la connexió "
                    +"amb la base de dades."+ e.getLocalizedMessage());
            throw new LlegirDAOException("GI:Llegir:Error a la base de dades, "
                    +"Item id:"+id+". "+e.getLocalizedMessage());

        }catch (NullPointerException e){
            log.error("GI:Llegir:El valor retornat és null per id: "+id+".{}"
                    + e.getLocalizedMessage());
            throw new LlegirDAOException("Valor null, Item id:"+id+". "
                    +e.getLocalizedMessage());
        
        }catch (LlegirDAOException e){
            log.error("GI:Llegir:Hi ha hagut un error llegint l'ítem id: "
                    +id+".{}", e.getLocalizedMessage());
            throw new LlegirDAOException("GI:Llegir:Error a la base de dades, "
                    +"Item id:"+id+". "+e.getLocalizedMessage());

        }catch (BuitException e){
            log.error("GI:Llegir:Item buit, id: "+id+"."
                    +e.getLocalizedMessage());
            throw new LlegirDAOException("Buit, Item id:"+id+". "
                    +e.getLocalizedMessage());
        }
        return it;
    }

    @Override
    public Iterator<?> llistat() throws LlistatDAOException{

        Iterator<Item> ll = null;
        try {
            openGestor();
            ll = this.llistatItems();
        } catch(HibernateException e){
            log.error("GI:Llistat:No s'ha pogut obentir la llista d`Ítems. "
                    +e.getLocalizedMessage());
            throw new LlistatDAOException("GI:Llistat:No s'ha pogut obentir la "
                    +"llista d`Ítems. "+e.getLocalizedMessage());
        }/*catch(BuitException e){
            log.error("GI:Llistat:Llista d`items buida. "
                    +e.getLocalizedMessage());
            throw new LlistatDAOException("GI:Llistat:Llista d`items buida. "
                    +e.getLocalizedMessage());
        }*/
        return ll;
    }

    @Override
    public Iterator<Item> llistat( int ini,int fi) throws LlistatDAOException{
        Iterator<Item> ll = null;
         try {
             openGestor();
             ll= dao.llista( ini, fi);
             //ll=this.llistatItems(ini, fi);
        }catch(HibernateException e){
            log.error("GI:Llistat:No s'ha pogut obentir la llista d`Ítems. "
                    +e.getLocalizedMessage());
            throw new LlistatDAOException("GI:Llistat:No s'ha pogut obentir la "
                    +"llista d`Ítems. "+e.getLocalizedMessage());
        }catch(BuitException e){
            log.error("GI:Llistat:Llista d`items buida. "
                    +e.getLocalizedMessage());
            throw new LlistatDAOException("GI:Llistat:Llista d`items buida. "
                    +e.getLocalizedMessage());
        }
        return ll;
    }
    
    public Iterator<Item> llistat_PERborrar( String camp, String valorCercat,int ini,int fi) throws LlistatDAOException{
        Iterator <Item> it=null;
        if ( (valorCercat==null) || (camp==null) ){
            it=this.llistat(ini, fi);
        }
        else {
            InjeccioCodi filtre =new InjeccioCodi();
            String cmp=filtre.netejar(camp);
            String valor=filtre.netejar(valorCercat);

            //TODO: 12-12-11:Emili: Falta fer la cerca per camp i valor
            //dao.llista(valor,ini, fi);

        }
        return it;
    }

    @Override
    public Iterator<Item> llistat(String campCerca, String valorCerca,
            int ini,int fi) throws LlistatDAOException{

        Iterator <Item> it=null;
        if ((valorCerca.equals("") || valorCerca==null)||
            (campCerca.isEmpty() ||campCerca==null)){
            it=this.llistat(ini, fi);
        }
        else {
            InjeccioCodi filtre =new InjeccioCodi();
            String campTaula=filtre.netejar(campCerca);
            Object crca=filtre.netejar(valorCerca);
            String cmp="like";
            try {
                openGestor();
                //Emili:09_01-2012: Actualment no es fa servir. però es deixa
                //                  actiu.
                if (campTaula.equalsIgnoreCase("datapub") ){
                    cmp="<";

                    //La data és correcta ?
                    if (! filtre.comprovarData(crca.toString()))
                       throw new LogicException("GI:Llistat:La data indicada "
                               +"és errónia.");
                    else {
                        //Obtenim un objecte data.
                        //Si treballéssim amb integers també s'hauria de filtrar
                        SimpleDateFormat sdf =
                                new SimpleDateFormat(Config.FORMAT_DATA);
                        sdf.setLenient(false);
                        crca=sdf.parse(crca.toString());
                    }
                }
                else if (campTaula.equalsIgnoreCase("autor") ) cmp="like";
                else if (campTaula.equalsIgnoreCase("nom") ) cmp="like";
                else if (campTaula.equalsIgnoreCase("tipus") ){
                cmp="=";
                campTaula="arxiu."+campTaula;
            }
            else
                throw new LogicException("GI:Llistat:hi ha un valor indicat "
                        +"de forma incorrecte");

            it=dao.llista(campTaula, cmp, crca, ini, fi);


            } catch (HibernateException ex) {
                log.error("GI:Llistat:Error a la base de dades obtenint la "
                        +"llista d'ítems."+ex.getLocalizedMessage());
                throw new LlistatDAOException("GI:Llistat:Error a la base de "
                        +"dades obtenint la llista d'ítems");
            } catch (BuitException ex) {
                log.error("GI:Llistat:Llista sense ítems."
                        +ex.getLocalizedMessage());
                throw new LlistatDAOException("GI:Llistat:Llista sense ítems");
            }catch (NullPointerException ex) {
                log.error("GI:Llistat:Hi ha valors buits."
                        +ex.getLocalizedMessage());
                throw new LlistatDAOException("GI:Llistat:Hi ha valors buits");
            }catch (LogicException ex) {
                log.error("GI:Llistat:ERROR lògics: "+ex.getLocalizedMessage());
                throw new LlistatDAOException("GI:Llistat:La cadena de cerca "
                        +"no està ben condtruida");
            }catch (ParseException ex) {
                log.error("GI:Llistat:ERROR de filtre: "
                        +ex.getLocalizedMessage());
                throw new LlistatDAOException("GI:Llistat:La data no s'ha pogut"
                       +" processar");
            }
        }
        return it;
    }

    public Iterator<Item> llistatItems() throws LlistatDAOException{
            //HibernateException, BuitException {
        Iterator<Item> llista=null;
        try{
            openGestor();
            llista=dao.llista();
        }catch (HibernateException ex) {
            log.error("GI:LlistatItems:Error a la base de dades obtenint la"
                +" llista d'ítems."+ex.getLocalizedMessage());
            throw new LlistatDAOException("GI:LlistatItems:Error a la base de"
                        +" dades obtenint la llista d'ítems");

        } catch (BuitException ex) {
            log.error("GI:LlistatItems:Llista sense ítems."
                +ex.getLocalizedMessage());
            throw new LlistatDAOException("GI:LlistatItems:Llista sense ítems");

        }catch (NullPointerException ex) {
            log.error("GI:LlistatItems:Hi ha valors buits."
                +ex.getLocalizedMessage());
            throw new LlistatDAOException("GI:LlistatItems:Hi ha valors buits");

        }

        return llista;
    }
    public Iterator<Item> llistatItems(int ini, int fi)throws LlistatDAOException{
            //HibernateException, BuitException {
        Iterator<Item> llista=null;
        List<Item> llistaAcotada=new LinkedList<Item>();
        Item item=null;

        try {
            openGestor();
            //TODO:20-12-11:Emili: cal passar aquest mètode pel declarat a la interfície
            llista=this.llistatItems();
            for (int i=0; (i<=fi)&&(llista.hasNext());i++){
                item=llista.next();
                if (ini<=i ) {
                    llistaAcotada.add(item);
                }
            }
        }catch (HibernateException ex) {
            log.error("GI:LlistatItems:Error a la base de dades obtenint la"
                +" llista d'ítems acotada."+ex.getLocalizedMessage());
            throw new LlistatDAOException("GI:LlistatItems:Error a la base de"
                        +" dades obtenint la llista d'ítems acotada");

        }catch (NullPointerException ex) {
            log.error("GI:LlistatItems: Tenim valors nulls."
                +ex.getLocalizedMessage());
            throw new LlistatDAOException("GI:LlistatItems:Tenim valors nulls");
        }

        return llistaAcotada.iterator();
    }

    public Iterator<Item> llistatItems(String ordre, int quants )
            throws LlistatDAOException{
            //HibernateException, BuitException {

        Iterator<Item> llistaAcotada=null;
        try {
            openGestor();
            llistaAcotada=dao.llista(ordre, quants);
        }catch (HibernateException ex) {
            log.error("GI:LlistatItems:Error a la base de dades obtenint la"
                +" llista d'ítems filtrada."+ex.getLocalizedMessage());
            throw new LlistatDAOException("GI:LlistatItems:Error a la base de"
                        +" dades obtenint la llista d'ítems filtrada");

        } catch (BuitException ex) {
            log.error("GI:LlistatItems:Llista filtrada sense ítems."
                +ex.getLocalizedMessage());
            throw new LlistatDAOException("GI:LlistatItems:Llista filtrada "
                    +"sense ítems");

        }catch (NullPointerException ex) {
            log.error("GI:LlistatItems:Hi ha valors buits a la llista filtrada."
                +ex.getLocalizedMessage());
            throw new LlistatDAOException("GI:LlistatItems:Hi ha valors buits"
                    +" a la llista filtrada");
        }

        return llistaAcotada;
    }

    public Iterator<Item> llistaTopTen( ) throws LlistatDAOException{
            //HibernateException, BuitException {
        Iterator<Item> llista = null;
        try {
            openGestor();
            llista=dao.llista("visites", "desc", 10);

        }catch (HibernateException ex) {
            log.error("GI:LlistatTopTen:Error a la base de dades obtenint la"
                +" llista d'ítems."+ex.getLocalizedMessage());
            throw new LlistatDAOException("GI:LlistatTopTen:Error a la base de"
                        +" dades obtenint la llista d'ítems");
        } catch (BuitException ex) {
            log.error("GI:LlistatTopTen:Llista sense ítems."
                +ex.getLocalizedMessage());
            throw new LlistatDAOException("GI:LlistatTopTen:Llista sense ítems");

        }catch (NullPointerException ex) {
            log.error("GI:LlistatTopTen:Hi ha valors buits."
                +ex.getLocalizedMessage());
            throw new LlistatDAOException("GI:LlistatTopTen:Hi ha valors buits");

        }
        return llista;
    }

    public Iterator<Item> llistaUltimsItems() throws LlistatDAOException {
            //HibernateException, BuitException{
        Iterator<Item> llista=null;
            try{
                openGestor();
                llista=this.llistatItems("desc", Config.nUltimsItems);
            }catch (HibernateException ex) {
            log.error("GI:LlistatUltims:Error a la base de dades obtenint la"
                +" llista d'ítems."+ex.getLocalizedMessage());
            throw new LlistatDAOException("GI:LlistatUltims:Error a la base de"
                        +" dades obtenint la llista d'ítems");
            }catch (NullPointerException ex) {
                log.error("GI:LlistatUltims:Hi ha valors buits."
                    +ex.getLocalizedMessage());
            throw new LlistatDAOException("GI:LlistatUltims:Hi ha valors buits");
            }
        return llista;
    }

     /**
     *
     * @return Nombre d'ítems del sistema
     */
    //Per implementar la interficie
    @Override
    public int num() throws HibernateException,BuitException{

        return this.numItems();
    }

    /**
     *          Retorna la llista ítems que coincideix amb "nom"
     * @param valor
     * @return
     * @throws HibernateException
     * @throws BuitException
     */
    @Override
    public int num(String valor) throws HibernateException,BuitException{

        //08-1-11 return this.num("nom", "like", valor);
        return this.num("nom", valor);
    }
    /**
     *
     * @param camp
     * @param cmp
     * @param valor
     * @return retorna el nombre d'elements segons la condicio camptaula i valor
     * @throws HibernateException
     * @throws BuitException
     */
    public int num(String campTaula, String valor) throws HibernateException, BuitException{
        int nItems=Config.valorNullInt;
         String camp=Config.valorNullStr;
         String cmp=Config.valorNullStr;
         Object v=null;
         Date data=null;

        try{
            openGestor();
            InjeccioCodi filtre =new InjeccioCodi();
            camp=filtre.netejar(campTaula);
            v=filtre.netejar(valor);

            if (camp.equalsIgnoreCase("datapub") ){
                cmp="<";

                //La data és correcta ?
                if (! filtre.comprovarData(v.toString()))
                 throw 
                  new LogicException("GI:num:hi ha una construcció incorrecta");
                else {
                  //Obtenim un objecte data
                    SimpleDateFormat sdf =
                        new SimpleDateFormat(Config.FORMAT_DATA);
                    sdf.setLenient(false);
                    v=sdf.parse(v.toString());
                }
            }
            else if (camp.equalsIgnoreCase("autor") ) cmp="like";
            else if (camp.equalsIgnoreCase("nom") ) cmp="like";
            else if (camp.equalsIgnoreCase("tipus") ){
                cmp="=";
                camp="arxiu."+camp;
            }
            else throw 
               new LogicException("GI:num:no hi ha un valor de forma correcte");

            //Eines.escriu("Classe: "+v.getClass().getSimpleName());

            nItems=dao.quantsItems(camp,cmp,v);

            //5-1-11 if (nContenidors>0)  GestorContenidors.numContenidors=nContenidors;
            if (nItems <0 )
            throw new BuitException("GU:num:Classe Contenidor, counter="
                    +String.valueOf(nItems));
        }catch (HibernateException e){
            log.error("GI:num:Falla la connexió amb la bddd. Error en conèixer "
                    +"el nombre d`ítems."+e.getLocalizedMessage());
            throw e ;
        }catch (BuitException e){
            log.error("GI:num:No hi ha ítems."+e.getLocalizedMessage());
            throw e ;
        }catch (NullPointerException e){
            log.error("GI:num:Algun valor null."+e.getLocalizedMessage());
            throw new BuitException("GI:num:Algun valor null."
                    +e.getLocalizedMessage()) ;
            }
         catch(LogicException e){
            log.error("GI:num:construcció incorrecta."+e.getLocalizedMessage());
            throw new BuitException("GI:Num:construcció incorrecta. "
                    +e.getLocalizedMessage());
        }catch (ParseException e){
            log.error("GI:Num:Data passada al mètode incorecta."
                    +valor.toString()+"."+e.getLocalizedMessage());
        }
        //}
        //15-12-11 return GestorContenidors.numContenidors;
        return nItems;
        
    }

    public int numItems() throws HibernateException,BuitException{
        int nItems=0;
      
            try{
                openGestor();
                nItems=dao.quantsItems();
                if (nItems>0){
                  if (nItems!=GestorItems.numItems) GestorItems.numItems=nItems;
                }else throw new BuitException("GI:numItems:Classe Items, count="
                        +String.valueOf(nItems));
            }catch (HibernateException e){
                    this.getLog().error("GI:numITems:Error en conèixer el "
                            +"nombre d'ítems."+e.getLocalizedMessage());
                    throw e ;
            }catch (BuitException e){
                    this.getLog().error("GI:numItems:nombre d'ítems buit."
                            +e.getLocalizedMessage());
                    throw e ;
            }catch (NullPointerException e){
                    this.getLog().error("GI:numItems:El nombre d'ítems és null."
                            +e.getLocalizedMessage());
                    throw new BuitException("GI:numItems:El nombre d'ítems " +
                            "és null.");
            }
        return GestorItems.numItems;
    }
    /**
     *
     * @param augment , 1=augmenta en 1, -1=disminueix un valor
     * @return retorna el nombre d'ítems +1
     * @throws HibernateException
     * @throws BuitException
     */
    public int numItems(Integer augment)
            throws HibernateException,BuitException{

        //s'obté de la base de dades el nou valor
        Integer nouValor=this.numItems();

        if (augment.equals(1)) nouValor++;
        else if (augment.equals(-1) && nouValor > 0) nouValor--;

        GestorItems.numItems=nouValor;

        return GestorItems.numItems;
    }

    /**
     *
     * @return Tenim una visita més per a un ítem id donat
     */
    public int mesVisita(Long id) {
            //throws HibernateException, NoExisteixException{

        int visites=0;

        try{
            openGestor();
            visites=dao.mesVisita( id);
        }catch (HibernateException e){
            this.getLog().error("GI:mesVisita:Error accecint a la bdd per "
                    +"actualitzar les visites de l'ítem."+id.toString());

        }catch (NoExisteixException e){
            this.getLog().error("GI:mesVisita:L'id indicat no existeix. id:"
                    +id.toString());

        }catch (BuitException e){
            this.getLog().error("GI:mesVisita:L'id indicat no existeix. id :"
                    +id.toString());
        }catch (NullPointerException e){
            this.getLog().error("GI:mesVisita:visites o id amb valor null."
                    +e.getLocalizedMessage());
        }
        return visites;
    }

    public int nombreVisites(Long id) throws HibernateException, NoExisteixException{
        int visites=0;

            try{
                openGestor();
                visites=dao.nombreVisites(id);

            }catch (HibernateException e){
                    this.getLog().error("GI:nombreVisites:Error accedint a "
                            + "la bdd per obtenir les visites de l'ítem :"
                            +id.toString()+". "+e.getLocalizedMessage());
            }catch (NoExisteixException e){
                    this.getLog().error("GI:nombreVisites:L'id indicat no "
                            +"existeix. Id:"+id.toString()
                            +". "+e.getLocalizedMessage());
            }catch (BuitException e){
                    this.getLog().error("GI:nombreVisites:L'id indicat no "
                            +"existeix. Id :"+id.toString()
                            +". "+e.getLocalizedMessage());
            }catch (NullPointerException e){
                    this.getLog().error("GI:nombreVisites:el nombre de visites "
                            +"o l'id són null."+e.getLocalizedMessage());
            }
        return visites;
    }


    /*****************************************************
     *
     * TESTS
     * 
     *****************************************************/
    private void testAfegirItem(GestorItems gi){
        Item item=null;
        Random aleatori= new Random();
        java.util.Date data = new java.util.Date();
        Arxiu arxiu= new Arxiu("arxiu1.zip","zip","/srv/diposit/fitxers/",200);
        GestorContenidors gc = GestorContenidors.getInstance();
        Contenidor c=null;
        try {
            c = gc.llegirContenidor(1L);
        } catch (LlegirDAOException ex) {
            this.getLog().error("Error:{}",ex.getLocalizedMessage());
        }
        item= new Item("Item: "+aleatori.nextInt(), data,"descripcio varia",false, c, arxiu);
        c.addItem(item);
        try {

            gc.modificar(c); //gi.afegirItem(item);
        } /*catch (AfegirDAOException ex) {
            this.log.error("Error en afegir l`ítem {}",item.toString());
        } catch (BuitException ex) {
            this.log.error("Error en afegir l`ítem {}",item.toString());
        }*/catch (ModDAOException ex) {
            this.getLog().error("Error en afegir l`ítem {}",item.toString());
        }
    }
   
    private void testllegirItem(Class classe , Long id,GestorItems gi){
       java.util.Date data = new java.util.Date();
       Item item=null;
        try {
            item = (Item)gi.llegirItem(id);
            Eines.escriu(item);
            //if (item !=null) Eines.escriu(item.getClass().getCanonicalName());
             if (item instanceof Item){
                Item iv=(Item)item;
               // Eines.escriu("Ubicacio:"+iv.getArxiu().getUbicacio());
            }
        } catch (HibernateException ex) {
            this.getLog().error("Error a la connexió amb la base de dades {}", ex.getLocalizedMessage());
        } catch (LlegirDAOException ex) {
            this.getLog().error("Error de lectura. {}", ex.getLocalizedMessage());
        }
       

    }
    private void testNumItems(GestorItems gi){
        try {
            Eines.escriu(gi.numItems());
        } catch (HibernateException ex) {
            this.getLog().error("Error en obtenir el nombre d'ítems. {}", ex.getLocalizedMessage());
        } catch (BuitException ex) {
            this.getLog().error("nombre d'ítems incorrecte. {}", ex.getLocalizedMessage());
        }

    }
    private void testNombreVisites(Long id, GestorItems gi){
        //Long id=1L;
        try {
            Eines.escriu(gi.nombreVisites(id));
        } catch (HibernateException ex) {
            this.getLog().error("Error en obtenir el nombre de visites de l'ítes. {}", ex.getLocalizedMessage());
        } catch (NoExisteixException ex) {
            this.getLog().error("L'item indicat no existeix id : {}"+id, ex.getLocalizedMessage());
        }
    }
    private void testmesVisita(GestorItems gi){
        Long id=1L;
        try {
            Eines.escriu(gi.mesVisita(id));
        } catch (HibernateException ex) {
            this.getLog().error("Error en obtenir el nombre d'ítems."
                    + ex.getLocalizedMessage());
        }/* catch (NoExisteixException ex) {
            this.getLog().error("nombre d'ítems incorrecte."
         + ex.getLocalizedMessage());
        }*/

    }
    private void testLlistat(GestorItems gi){
       try {
            Iterator it=gi.llistaUltimsItems();
            while (it.hasNext()){
                Item i=(Item)it.next();
                Eines.escriu(i);
            }

        } catch (HibernateException ex) {
            this.getLog().error("Error en obtenir la llista contenidors. "
                    +ex.getLocalizedMessage());
        } catch (LlistatDAOException ex) {
            this.getLog().error("llista buida de contenidors. "
                    + ex.getLocalizedMessage());
        }

    }
    private void testEliminar(GestorItems gi){
        Arxiu arxiu; //= new Arxiu("doc.zip","zip","/srv/diposit/",123);
        Item it ;//= new Item("emili",new java.util.Date(),"descri",true,0,"vom van",arxiu);
        Contenidor c;
        GestorContenidors gc= GestorContenidors.getInstance();
        try {

            //c=gc.llegirContenidor(1L);
            //it=(Item)c.getItems().get(10);
            //Eines.escriu(it);
            gc.treureItem(10L, 1L);
            //gc.treureItem(it, c);

            gi.eliminar(10L, 1L);

        }catch(Exception e){
            Eines.escriu(e.getLocalizedMessage());
            gc.tancar();
        }
    }

   /**************************************
    * MAIN
    */
   public static void main(String args[]){
        
        GestorItems gi=new GestorItems();

    
        //gi.testAfegirItem(gi);
        //gi.testAfegirItemVisual(gi);
        //gi.testllegirItem(Item.class, 6001L, gi);
        //gi.testllegirItem(Item.class, 10L, gi);
        try {
            /*        Iterator<Item> li=null;
            try {
            li = gi.llistat(0, 12);
            } catch (LlistatDAOException ex) {
            Logger.getLogger(GestorItems.class.getName()).log(Level.SEVERE, null, ex);
            }
            while (li.hasNext()){
            Eines.escriu(li.next().getNom());
            }
             */
            Eines.escriu(gi.num("pro"));
            Eines.escriu(gi.numItems());
        } catch (HibernateException ex) {
            Logger.getLogger(GestorItems.class.getName()).log(Level.SEVERE, null, ex);
        } catch (BuitException ex) {
            Logger.getLogger(GestorItems.class.getName()).log(Level.SEVERE, null, ex);
        }

        gi.tancar();


    }

}
